package halftone.errdiff.pipeline

import chisel3._
import chisel3.util.{Counter, Decoupled}
import halftone.ErrDiffConfig
import halftone.errdiff.ErrDiffCorePipParam._
import tools.bus.BramNativePortFull

class PixelGetPip(config: ErrDiffConfig) extends Module {
  val io = IO(new Bundle {
    val in = Flipped(Decoupled(new Bundle {
      val pos = UInt(config.posWidth.W)
    }))
    val img = Flipped(new BramNativePortFull(config.bramDataBits, config.bramAddrBits))
    val end = Output(Bool())
    val out = Decoupled(new PixelGet2ErrorInPip(config.pixelWidth, config.posWidth))
    val stop = Input(Bool())
  })

  // Registers(for value storage and state presentation)
  val pos         = Reg(UInt(config.posWidth.W))
  val pix         = Reg(UInt(config.pixelWidth.W))
  val busy        = RegInit(false.B)
  val resultValid = RegInit(false.B)

  io.out.valid := resultValid
  io.in.ready  := true.B
  // useless signals
  io.img.we  := false.B
  io.img.din := 0.U

  /*
   * Read pixel from image storage
   */
  io.img.en   := io.in.fire
  io.img.addr := io.in.bits.pos

  // Emit outputs
  io.out.bits.pos := pos
  io.out.bits.pix := pix

  val (cnt, cntWrap) = Counter(busy && !resultValid, CycleNr)
  io.end := cntWrap

  pix := io.img.dout

  when(cntWrap && !io.stop) { resultValid := true.B }
  when(io.out.fire) {
    resultValid := false.B
  }
  when(io.in.fire) {
    pos  := io.in.bits.pos
    busy := true.B
  }
}
